package vip.xiaomaoxiaoke.joinbymemory.support;


import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import vip.xiaomaoxiaoke.joinbymemory.JoinItemExecutor;
import vip.xiaomaoxiaoke.joinbymemory.JoinItemExecutorFactory;
import vip.xiaomaoxiaoke.joinbymemory.JoinItemsExecutor;
import vip.xiaomaoxiaoke.joinbymemory.JoinItemsExecutorFactory;
import vip.xiaomaoxiaoke.joinbymemory.annotation.JoinByMemoryConfig;
import vip.xiaomaoxiaoke.joinbymemory.enums.JoinByMemeoryExecutorType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;


@Slf4j
public class DefaultJoinItemsExecutorFactory implements JoinItemsExecutorFactory {
    private final List<JoinItemExecutorFactory> joinItemExecutorFactories;
    private final Map<String, ExecutorService> executorServiceMap;

    public DefaultJoinItemsExecutorFactory(Collection<? extends JoinItemExecutorFactory> joinItemExecutorFactories,
                                           Map<String, ExecutorService> executorServiceMap) {
        this.joinItemExecutorFactories = Lists.newArrayList(joinItemExecutorFactories);

        // 按执行顺序进行排序
        AnnotationAwareOrderComparator.sort(this.joinItemExecutorFactories);
        this.executorServiceMap = executorServiceMap;
    }


    @Override
    public <D> JoinItemsExecutor<D> createFor(Class<D> cls,String group) {
        // 依次遍历 JoinItemExecutorFactory， 收集 JoinItemExecutor 信息
        List<JoinItemExecutor<D>> joinItemExecutors = this.joinItemExecutorFactories.stream()
                .flatMap(factory -> factory.createForType(cls,group).stream())
                .collect(Collectors.toList());

        // 从 class 上读取配置信息
        JoinByMemoryConfig joinByMemoryConfig = cls.getAnnotation(JoinByMemoryConfig.class);

        // 封装为 JoinItemsExecutor
        return buildJoinItemsExecutor(cls, joinByMemoryConfig, joinItemExecutors);
    }

    /**
     * 根据配置获取执行器对象，以及为该对象分配执行器类型
     * */
    private  <D> JoinItemsExecutor<D> buildJoinItemsExecutor(Class<D> cls, JoinByMemoryConfig joinByMemoryConfig, List<JoinItemExecutor<D>> joinItemExecutors){
        // 使用 串行执行器
        if(joinByMemoryConfig == null || joinByMemoryConfig.executorType() == JoinByMemeoryExecutorType.SERIAL){
            log.info("joinByMemoryConfig for {} use serial executor", cls);
            return new SerialJoinItemsExecutor<>(cls, joinItemExecutors);
        }

        // 使用 并行执行器
        if (joinByMemoryConfig.executorType() == JoinByMemeoryExecutorType.PARALLEL){
            log.info("joinByMemoryConfig for {} use parallel executor, pool is {}", cls, joinByMemoryConfig.executorName());
            ExecutorService executor = executorServiceMap.get(joinByMemoryConfig.executorName());
            Preconditions.checkArgument(executor != null);
            return new ParallelJoinItemsExecutor<>(cls, joinItemExecutors, executor);
        }
        throw new IllegalArgumentException();
    }
}
